# ============================================================
# * Copyright © hk. 2022-2025. All rights reserved.
# * File name: CMakeLists.txt
# * Author   : 苏木
# * Date     : 2025-05-22
# * Version  : 
# * Description: cmake version 3.16.3
# ============================================================
## https://cmake.com.cn/cmake/help/latest/guide/tutorial/index.html
## https://cmake.org/cmake/help/latest/

# 指定 CMake 的最低版本要求
# --------------------------------------------------
cmake_minimum_required(VERSION 3.10)


# 设置项目名称和使用的编程语言
# --------------------------------------------------
project(SPROJECT C)


# 指定可执行程序和源文件
# --------------------------------------------------
add_executable(app_demo.out main.c)

# Macro和function的区别
# --------------------------------------------------

# 1. 区别1：函数会产生新作用域；宏是把执行代码替换到调用位置
#    函数和宏的参数处理是相同的，除了一个非常重要的区别：
#      对于函数来说，每个参数都是一个CMake变量，例如：可以作为变量在if()语句中进行判断。
#      相比之下，宏参数是字符串替换项，因此无论使用什么作为宏调用的参数，基本上都会粘贴到宏主体中的参数中。如果在if()语句中使用宏参数，那么参数将视为字符串而不是变量。
message(STATUS "==> ${CMAKE_VERSION} 演示1: 基础参数传递demo")
# 定义函数
function(test_func_argument arg)
	message(STATUS "[函数] 收到参数: ${arg}, ARGC: ${ARGC}, ARGV: ${ARGV}, ARGN: ${ARGN}")
    message(STATUS "	  ARGV0: ${ARGV0}") # 打印ARGV0参数值
    
    list(LENGTH ARGV argv_len) # 打印参数个数
    message(STATUS "	  length of ARGV: ${argv_len}")
    
    # 遍历打印各参数值
    set(i 0)
    while(i LESS ${argv_len})
        list(GET ARGV ${i} argv_value)
        message(STATUS "	  argv${i}: ${argv_value}")
        math(EXPR i "${i} + 1")
    endwhile()
    
    if (ARGV1)         # ARGV1 is a true variable
        message(STATUS "	  ARGV1: ${ARGV1}")
    endif()
    
    if (DEFINED ARGV2) # ARGV2 is a true variable
        message(STATUS "	  ARGV2: ${ARGV2}")
    endif()
    
    if (ARGC GREATER 2) # ARGC is a true variable
        message(STATUS "	  ARGC: ${ARGC}")
    endif()
    
    foreach (loop_var IN LISTS ARGN) # ARGN is a true variable
        message(STATUS "	  var: ${loop_var}")
    endforeach()
endfunction()
 
# 定义宏
macro(test_macro_argument arg)
	message(STATUS "[宏] 收到参数: ${arg}, ARGC: ${ARGC}, ARGV: ${ARGV}, ARGN: ${ARGN}")
    message(STATUS "	  ARGV0: ${ARGV0}") # 打印ARGV0参数值
    
    # 打印参数个数
    list(LENGTH ARGV argv_len)
    message(STATUS "	  length of ARGV: ${argv_len}")
    
    # 遍历打印各参数值
    set(i 0)
    while(i LESS ${argv_len})
        list(GET ARGV ${i} argv_value)
        message(STATUS "	  argv${i}: ${argv_value}")
        math(EXPR i "${i} + 1")
    endwhile()
    
    if (ARGV1)         # ARGV1 is not a variable
        message(STATUS "	  ARGV1: ${ARGV1}")
    endif()
    
    if (DEFINED ARGV2) # ARGV2 is not a variable
        message(STATUS "	  ARGV2: ${ARGV2}")
    else()
        message(STATUS "	  not defined ARGV2")
    endif()
    
    if (ARGC GREATER 2) # ARGC is not a variable
        message(STATUS "	  ARGC: ${ARGC}")
    endif()
    
    foreach (loop_var IN LISTS ARGN) # ARGN is not a variable
        message(STATUS "	  var: ${loop_var}")
    endforeach()
endmacro()
 
test_func_argument(22 33 44)
test_macro_argument(22 33 44)
# 输出结果：
# -- ==> 3.16.3 演示1: 基础参数传递demo
# -- [函数] 收到参数: 22, ARGC: 3, ARGV: 22;33;44, ARGN: 33;44
# --        ARGV0: 22
# --        length of ARGV: 3
# --        argv0: 22
# --        argv1: 33
# --        argv2: 44
# --        ARGV1: 33
# --        ARGV2: 44
# --        ARGC: 3
# --        var: 33
# --        var: 44
# -- [宏] 收到参数: 22, ARGC: 3, ARGV: 22;33;44, ARGN: 33;44
# --        ARGV0: 22
# --        length of ARGV: 0
# --        not defined ARGV2
message(STATUS "")

# 函数和宏中的ARGN是不同的，虽然都可以在内部使用${}访问，但是在宏中，它并不是一个变量，仅仅是字符串的替换
message(STATUS "==> ${CMAKE_VERSION} 演示1: function和macro中ARGN")
set(external_var "ORIGINAL")
function(my_func arg1)
    message(STATUS "[function]固定参数: ${arg1}")
    message(STATUS "[function]可变参数: ${ARGN}")  # 获取剩余参数
	if (DEFINED ARGN)
        message(STATUS "[function]defined ARGN")
	else()
		message(STATUS "[function]not defined ARGN")
    endif()
endfunction()
macro(my_macro arg1)
    message(STATUS "[macro]固定参数: ${arg1}")
    message(STATUS "[macro]可变参数: ${ARGN}")  # 获取剩余参数
	if (DEFINED ARGN)
        message(STATUS "[macro]defined ARGN")
	else()
		message(STATUS "[macro]not defined ARGN")
    endif()
endmacro()

my_func(a b c d)
my_macro(a b c d)

message(STATUS "")
# 输出如下：
# -- ==> 3.16.3 演示1: function和macro中ARGN
# -- [function]固定参数: a
# -- [function]可变参数: b;c;d
# -- [function]defined ARGN
# -- [macro]固定参数: a
# -- [macro]可变参数: b;c;d
# -- [macro]not defined ARGN